import fs from 'fs';
import { res_format } from './res_format';
import { tools } from './tools/tools';

export namespace eui_str_extract {
	export class EuiStrExtract {
		constructor(entery: string) {
			this.curRoot = entery;
			let res = new res_format.ResCheck(this.curRoot).BuildTree();
			let exmlPac: string[] = [];

			this.CollectExml(res.CurRoot, exmlPac);

			this.TakeStr(exmlPac);
		}

		private CollectExml(root: res_format.ResFolder, pac: string[]) {
			for (let folder of root.FoldersName) {
				this.CollectExml(root.GetFolderByName(folder)!, pac);
			}

			let path: string;
			if (root.FilesNum > 0) {
				for (let file of root.Files!) {
					path = `${this.curRoot}/${root.FullPath}/${file}`;
					if (/\w*\.exml$/.test(path)) {
						pac.push(`/${root.FullPath}/${file}`);
					}
				}
			}

		}

		private async TakeStr(exmls: string[]) {
			if (this.load()) {
				for (let file of exmls) {
					await this.ReplaceFunc(`${this.curRoot}${file}`);
				}

				this.Save();
			}
		}


		private async ReplaceFunc(path: string): Promise<boolean> {
			return new Promise<boolean>((fullfill, reject) => {
				let readStream = fs.createReadStream(path, { autoClose: true, encoding: "utf-8" });

				let content: string = '';
				readStream
					.on('data', (data) => {
						content += data;
					})
					.on('end', () => {
						let key: string;
						content = content.replace(/(?<=text=|label=)"(.*?)"|(?<=text\.\w+=)"(.*?)"/g, (str) => {
							key = tools.unescape(str.substring(1, str.length - 1), true);
							if (!key || !Number.isNaN(+key)) {
								return str;
							}
							if (!this.IsI18nKey(key) && !this.GetI18nVal(key)) {
								this.GenI18nKey(key);
							}

							if (this.GetI18nVal(key)) {
								return `"${this.GetI18nVal(key)}"`;
							}

							return `"${key}"`;
						});

						let writeStream = fs.createWriteStream(path)
							.on('finish', function () {
								fullfill(true);
							})
							.on('error', (e) => {
								reject(e);
							});

						writeStream.write(content);
						writeStream.end();
					})
					.on('error', (e) => {
						reject(e)
					});
			})
		}

		private GetI18nVal(key: string) {
			if (!key) {
				return key;
			}

			return this.i18nLangCache[key];
		}

		private IsI18nKey(key: string): boolean {
			return !!key && key.length > 2 && key[0] === 'U' && key[1] == 'I' && !Number.isNaN(+key.slice(2));
		}

		private GenI18nKey(val: string) {

			let timeStamp = Date.now() * 100;

			if (this.i18nCfgCache[`UI${timeStamp}`]) {
				while (!!this.i18nCfgCache[`UI${timeStamp}`]) {
					++timeStamp;
				}
			}

			let key = `UI${timeStamp}`;
			this.i18nCfgCache[key] = val;
			this.i18nLangCache[val] = key;
		}

		private load(): boolean {
			let config = tools.QueryEgretProperties(this.curRoot);
			let euiCfg = config?.auto_eui_str;
			let resPath = config?.path || tools.DEF_RES_PATH;
			if (!!euiCfg) {
				tools.CreateFolder(`${this.curRoot}/${resPath}/${euiCfg.eui_str_path}`);
				let cfg = fs.readFileSync(`${this.curRoot}/${resPath}/${euiCfg.eui_str_path}/${euiCfg.eui_str_name}`, { encoding: "utf-8", flag: "a+" });
				let data = JSON.parse(cfg || '{}');
				let dataArr = data[euiCfg.eui_str_key] || [];
				for (let data of dataArr) {
					this.i18nCfgCache[data[0]] = data[1];
					this.i18nLangCache[data[1]] = data[0];
				}
				return true;
			} else {
				console.warn('can not find config: "resource_cfg/auto_eui_str" on egretProperties');
			}

			return false;
		}

		private Save() {
			let config = tools.QueryEgretProperties(this.curRoot);
			let euiCfg = config?.auto_eui_str;
			if (!!euiCfg) {
				let file = fs.openSync(`${this.curRoot}/${config?.path || tools.DEF_RES_PATH}/${euiCfg.eui_str_path}/${euiCfg.eui_str_name}`, "w+");
				let saveArr = [];
				for (let key in this.i18nCfgCache) {
					saveArr.push([key, this.i18nCfgCache[key]]);
				}

				saveArr.sort((a, b) => {
					return tools.HashNum(a[0]) - tools.HashNum(b[0]);
				});

				let saveContent = { [euiCfg.eui_str_key]: saveArr }
				fs.writeFileSync(file, JSON.stringify(saveContent, undefined, "\t"), { encoding: "utf-8" });
				fs.closeSync(file);
			}
		}


		private i18nCfgCache: Record<string, string> = {};
		private i18nLangCache: Record<string, string> = {};
		private curRoot: string;
	}
}